import { useEffect, useCallback, useRef, useState } from 'react'
import { debounce, throttle, lazyLoadImages, PerformanceMonitor } from '@/utils/performance'

/**
 * Hook for debounced value
 */
export function useDebouncedValue<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value)
  
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value)
    }, delay)
    
    return () => {
      clearTimeout(handler)
    }
  }, [value, delay])
  
  return debouncedValue
}

/**
 * Hook for debounced callback
 */
export function useDebouncedCallback<T extends (...args: any[]) => any>(
  callback: T,
  delay: number
): T {
  const callbackRef = useRef(callback)
  callbackRef.current = callback
  
  const debouncedCallback = useCallback(
    debounce((...args: Parameters<T>) => {
      callbackRef.current(...args)
    }, delay),
    [delay]
  )
  
  return debouncedCallback as T
}

/**
 * Hook for throttled callback
 */
export function useThrottledCallback<T extends (...args: any[]) => any>(
  callback: T,
  delay: number
): T {
  const callbackRef = useRef(callback)
  callbackRef.current = callback
  
  const throttledCallback = useCallback(
    throttle((...args: Parameters<T>) => {
      callbackRef.current(...args)
    }, delay),
    [delay]
  )
  
  return throttledCallback as T
}

/**
 * Hook for lazy loading images
 */
export function useLazyLoadImages(deps: any[] = []) {
  useEffect(() => {
    const cleanup = lazyLoadImages()
    return cleanup
  }, deps)
}

/**
 * Hook for intersection observer
 */
export function useIntersectionObserver(
  ref: React.RefObject<Element>,
  options?: IntersectionObserverInit
): boolean {
  const [isIntersecting, setIsIntersecting] = useState(false)
  
  useEffect(() => {
    const element = ref.current
    if (!element) return
    
    const observer = new IntersectionObserver(([entry]) => {
      setIsIntersecting(entry.isIntersecting)
    }, options)
    
    observer.observe(element)
    
    return () => {
      observer.disconnect()
    }
  }, [ref, options?.root, options?.rootMargin, options?.threshold])
  
  return isIntersecting
}

/**
 * Hook for performance monitoring
 */
export function usePerformanceMonitor() {
  const monitorRef = useRef(new PerformanceMonitor())
  
  useEffect(() => {
    return () => {
      monitorRef.current.clearMarks()
    }
  }, [])
  
  return monitorRef.current
}

/**
 * Hook for viewport size
 */
export function useViewport() {
  const [viewport, setViewport] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
    isMobile: window.innerWidth < 768,
    isTablet: window.innerWidth >= 768 && window.innerWidth < 1024,
    isDesktop: window.innerWidth >= 1024,
  })
  
  useEffect(() => {
    const handleResize = throttle(() => {
      const width = window.innerWidth
      const height = window.innerHeight
      
      setViewport({
        width,
        height,
        isMobile: width < 768,
        isTablet: width >= 768 && width < 1024,
        isDesktop: width >= 1024,
      })
    }, 200)
    
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [])
  
  return viewport
}

/**
 * Hook for network status
 */
export function useNetworkStatus() {
  const [status, setStatus] = useState({
    online: navigator.onLine,
    effectiveType: (navigator as any).connection?.effectiveType || 'unknown',
    downlink: (navigator as any).connection?.downlink || 0,
    rtt: (navigator as any).connection?.rtt || 0,
    saveData: (navigator as any).connection?.saveData || false,
  })
  
  useEffect(() => {
    const handleOnline = () => setStatus(prev => ({ ...prev, online: true }))
    const handleOffline = () => setStatus(prev => ({ ...prev, online: false }))
    
    const handleConnectionChange = () => {
      const connection = (navigator as any).connection
      if (connection) {
        setStatus(prev => ({
          ...prev,
          effectiveType: connection.effectiveType || 'unknown',
          downlink: connection.downlink || 0,
          rtt: connection.rtt || 0,
          saveData: connection.saveData || false,
        }))
      }
    }
    
    window.addEventListener('online', handleOnline)
    window.addEventListener('offline', handleOffline)
    
    const connection = (navigator as any).connection
    if (connection) {
      connection.addEventListener('change', handleConnectionChange)
    }
    
    return () => {
      window.removeEventListener('online', handleOnline)
      window.removeEventListener('offline', handleOffline)
      
      if (connection) {
        connection.removeEventListener('change', handleConnectionChange)
      }
    }
  }, [])
  
  return status
}

/**
 * Hook for reduced motion preference
 */
export function useReducedMotion() {
  const [prefersReducedMotion, setPrefersReducedMotion] = useState(
    window.matchMedia('(prefers-reduced-motion: reduce)').matches
  )
  
  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
    
    const handleChange = (e: MediaQueryListEvent) => {
      setPrefersReducedMotion(e.matches)
    }
    
    mediaQuery.addEventListener('change', handleChange)
    return () => mediaQuery.removeEventListener('change', handleChange)
  }, [])
  
  return prefersReducedMotion
}

/**
 * Hook for lazy loading component
 */
export function useLazyComponent<T>(
  importFn: () => Promise<{ default: T }>,
  options?: { delay?: number; fallback?: T }
): T | undefined {
  const [component, setComponent] = useState<T | undefined>(options?.fallback)
  
  useEffect(() => {
    let mounted = true
    
    const loadComponent = async () => {
      if (options?.delay) {
        await new Promise(resolve => setTimeout(resolve, options.delay))
      }
      
      const module = await importFn()
      
      if (mounted) {
        setComponent(() => module.default)
      }
    }
    
    loadComponent()
    
    return () => {
      mounted = false
    }
  }, [])
  
  return component
}